from PySide import QtGui, QtCore
from main_window import Ui_MainWindow
from ControlNewDatabase import ControlNewDatabase
from ControlNewOrder import ControlNewOrder
from PDataBase import PDataBase
import os.path, datetime, functools


class ControlMainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(ControlMainWindow, self).__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.newDbAct.triggered.connect(self.newDataBase)
        self.ui.exitAct.triggered.connect(self.exit)
        self.ui.closeDbAct.triggered.connect(self.closeDatabase)
        self.ui.openDbAct.triggered.connect(self.openDatabase)
        self.ui.newRecordAct.triggered.connect(self.newRecord)
        self.ui.deleteRecordAct.triggered.connect(self.deleteRecord)
        self.ui.editRecordAct.triggered.connect(self.editRecord)
        self.ui.searchRecordAct.triggered.connect(self.searchRecord)
        self.ui.helpAct.triggered.connect(self.showReference)
        self.ui.aboutProgAct.triggered.connect(self.showAboutProgramm)

        self.ui.tabWidget.setCurrentIndex(1)
        self.ui.tabWidget.currentChanged.connect(
            lambda index: self.ui.newRecordAct.setEnabled(False) if index == 0 else self.ui.newRecordAct.setEnabled(True)
        )

        self.ui.tableClients.itemDoubleClicked.connect(functools.partial(self._doubleClicked, self.ui.tableClients))
        self.ui.tableClients.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
        self.ui.tableClients.customContextMenuRequested.connect(self.clientsContextMenu)
        self.ui.tableClients.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch)

        self.ui.tableOrders.itemDoubleClicked.connect(functools.partial(self._doubleClicked, self.ui.tableOrders))
        self.ui.tableOrders.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
        self.ui.tableOrders.customContextMenuRequested.connect(self.ordersContextMenu)
        self.ui.tableOrders.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch)

        self.ui.tableGoods.itemDoubleClicked.connect(functools.partial(self._doubleClicked, self.ui.tableGoods))
        self.ui.tableGoods.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
        self.ui.tableGoods.customContextMenuRequested.connect(self.goodsContextMenu)
        self.ui.tableGoods.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch)

        self.ui.tableProviders.itemDoubleClicked.connect(functools.partial(self._doubleClicked, self.ui.tableProviders))
        self.ui.tableProviders.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
        self.ui.tableProviders.customContextMenuRequested.connect(self.providersContextMenu)
        self.ui.tableProviders.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch)

        self.setMinimumWidth(1000)

        self.db = None

    def _initTable(self, tableWidget: QtGui.QTableWidget, tableName: str):
        """
        Заполнение таблиц-виджетов записями из соответвующих таблиц БД.
        """
        # Очистка всей таблицы.
        tableWidget.clear()
        while tableWidget.rowCount() > 0:
            tableWidget.removeRow(0)

        # Получение табллицы из БД.
        table = self.db.getTable(tableName)

        # Отображение записей в соответсвии с особенностями таблиц.
        if tableName == 'Заказы':
            columns = table.columns
            columns[1] = (1, 'Клиент', 'VARCHAR')
            records = self.db.selectByQuery(
                fromTables="""`Заказы`, `Клиенты`""",
                select="""`Заказы`.`Id`, `Заказы`.`Наименование`, `Клиенты`.`Название`, `Заказы`.`Дата`, `Заказы`.`Время доставки`, `Заказы`.`Дополнительные расходы`, `Заказы`.`Описание`, `Заказы`.`Оплачено`""",
                where="""`Заказы`.`Клиент` = `Клиенты`.`Id`"""
            )
            colors = [('#ffffff',) for r in records]
        elif tableName == 'Клиенты':
            columns = table.fetchColumnsWithoutForeignKeys()
            records = table.select(selectTo=[col[1] for col in columns], orderBy=['Приоритет'], desc=True)
            colors = self.db.selectByQuery(
                fromTables="""`Цветовая_дифференциация`
                    JOIN `Клиенты` ON `Цветовая_дифференциация`.`Id` = `Клиенты`.`Цвет`
                    ORDER BY `Клиенты`.`Приоритет` DESC
                """,
                select="""`Цветовая_дифференциация`.`Цвет`""",
            )
        else:
            columns = table.fetchColumnsWithoutForeignKeys()
            records = table.select(selectTo=[col[1] for col in columns])
            colors = [('#ffffff',) for r in records]

        tableWidget.setColumnCount(len(columns))
        tableWidget.setHorizontalHeaderLabels([col[1] for col in columns])

        # Отображение каждой записи в таблице-виджете.
        for record, color in zip(records, colors):
            tableWidget.setRowCount(tableWidget.rowCount() + 1)
            col = 0
            for item in record:
                itemTableWidget = QtGui.QTableWidgetItem(item.__str__() if columns[col][2] != 'BOOL' else 'Да' if item == 1 else 'Нет')
                itemTableWidget.setBackground(QtGui.QColor(color[0]))
                tableWidget.setItem(tableWidget.rowCount() - 1, col, itemTableWidget)
                col += 1
        # Скрытие от пользователя первого столбца таблицы, содержащего первичный ключ.
        tableWidget.setColumnHidden(0, True)

    def _doubleClicked(self, tableWidget, item):
        """
        Отображение содержимого поля в таблице.
        """
        name = tableWidget.horizontalHeaderItem(item.column()).text()

        itemContentsDialog = QtGui.QDialog(self)
        itemContentsDialog.setWindowTitle('{}'.format(name))
        itemContentsDialog.setWindowFlags(QtGui.QWidget.windowFlags(self) ^ QtCore.Qt.WindowContextHelpButtonHint)

        buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok)
        buttonBox.accepted.connect(itemContentsDialog.accept)

        textWidget = QtGui.QTextEdit()
        textWidget.setReadOnly(True)
        textWidget.setPlainText(item.text())

        vboxLayout = QtGui.QVBoxLayout()
        vboxLayout.addWidget(textWidget)
        vboxLayout.addWidget(buttonBox)

        itemContentsDialog.setLayout(vboxLayout)
        itemContentsDialog.exec_()

    def _displayEditRecordDialog(self, title, table, record=None):
        """
        Отображение диалога для создания/редактирования записи в указанной таблице.
        """
        # Новая запись полученная из диалога.
        newRecord = {}

        # Создание диалога пользователя.
        dialog = QtGui.QDialog(self)
        dialog.setWindowTitle(title)
        dialog.setWindowFlags(QtGui.QWidget.windowFlags(dialog) ^ QtCore.Qt.WindowContextHelpButtonHint)

        # Добавление кнопок.
        buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(dialog.accept)
        buttonBox.rejected.connect(dialog.reject)

        # Создание лейаута с виджетами.
        gridLayout = QtGui.QGridLayout()

        glRow = 0 # номер строки в лейауте.
        # Получение столбцов таблицы, без учета первичных и вторичных ключей.
        columns = table.fetchColumnsWithoutKeys()
        # Добавление виджетов в зависимости от типа данных.
        for glRow, col in enumerate(columns):
            gridLayout.addWidget(QtGui.QLabel(col[1], self), glRow, 1)

            if col[2] == 'INTEGER':
                widget = QtGui.QSpinBox()
                widget.setMaximum(999999999)
                if record is not None:
                    widget.setValue(record[col[1]])
            elif col[2] == 'REAL':
                widget = QtGui.QDoubleSpinBox()
                widget.setMaximum(999999999)
                widget.setSuffix(' руб.')
                if record is not None:
                    widget.setValue(record[col[1]])
            elif col[2] == 'TEXT':
                widget = QtGui.QTextEdit()
                if record is not None:
                    widget.setText(record[col[1]])
            elif col[2] == 'VARCHAR':
                widget = QtGui.QLineEdit()
                widget.setMaxLength(50)
                if record is not None:
                    widget.setText(record[col[1]])
            elif col[2] == 'DATE':
                widget = QtGui.QDateEdit(datetime.date.today())
                if record is not None:
                    widget.setDate(record[col[1]])
            elif col[2] == 'TIMESTAMP':
                widget = QtGui.QDateTimeEdit(datetime.datetime.today())
                if record is not None:
                    widget.setDateTime(record[col[1]])
            elif col[2] == 'BOOL':
                widget = QtGui.QCheckBox('', self)
                if record is not None:
                    widget.setChecked(record[col[1]])
            else:
                widget = QtGui.QPlainTextEdit()
                if record is not None:
                    widget.setPlainText(record[col[1]])
            gridLayout.addWidget(widget, glRow, 2)

        gridLayout.addWidget(buttonBox, glRow + 1, 1, 1, 2, QtCore.Qt.AlignHCenter)

        # Добавление лейаута в диалог и отображение его.
        dialog.setLayout(gridLayout)
        dialog.exec_()

        # Результат диалога.
        if dialog.result() == QtGui.QDialog.Accepted:
            for glRow in range(gridLayout.rowCount() - 1):
                # Определение типа виджета и получение данных.
                label = gridLayout.itemAtPosition(glRow, 1).widget()
                widget = gridLayout.itemAtPosition(glRow, 2).widget()

                if widget.inherits('QSpinBox') or widget.inherits('QDoubleSpinBox'):
                    data = widget.value()
                elif widget.inherits('QLineEdit'):
                    data = widget.text()
                elif widget.inherits('QPlainTextEdit') or widget.inherits('QTextEdit'):
                    data = widget.toPlainText()
                elif widget.inherits('QDateEdit'):
                    data = widget.date().toPython()
                elif widget.inherits('QDateTimeEdit'):
                    data = widget.dateTime().toPython()
                elif widget.inherits('QCheckBox'):
                    data = widget.isChecked()
                # Получение имени поля таблицы и добавление данных.
                name = label.text()
                if data is not None:
                    newRecord[name] = data

            # Если создается новая запись.
            if record is None:
                for col in table.foreignKeys:
                    newRecord[col[0]] = None

        return newRecord

    def _displaySearchRecordDialog(self, title: str, table):
        """
        Отображение диалога поиска записей по критериям.
        """
        # Критерии поиска записей.
        filters = {}

        # Создание диалога пользователя.
        dialog = QtGui.QDialog(self)
        dialog.setWindowTitle(title)
        dialog.setWindowFlags(QtGui.QWidget.windowFlags(dialog) ^ QtCore.Qt.WindowContextHelpButtonHint)

        # Добавление кнопок.
        buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(dialog.accept)
        buttonBox.rejected.connect(dialog.reject)

        # Получение столбцов таблицы, без учета первичных и вторичных ключей и полей описания (тип TEXT).
        columns = [col for col in table.fetchColumnsWithoutKeys() if col[2] != 'TEXT']

        # Создание лейаута с виджетами.
        gridLayout = QtGui.QGridLayout()

        glRow = 0 # номер строки в лейауте.
        # Добавление виджетов в зависимости от типа данных.
        for glRow, col in enumerate(columns):
            gridLayout.addWidget(QtGui.QCheckBox('', self), glRow, 1)
            gridLayout.addWidget(QtGui.QLabel(col[1], self), glRow, 2)

            if col[2] == 'VARCHAR':
                widget = QtGui.QLineEdit()
                widget.setMaxLength(50)
                gridLayout.addWidget(widget, glRow, 3)
            elif col[2] == 'BOOL':
                widget = QtGui.QCheckBox('', self)
                gridLayout.addWidget(widget, glRow, 3)
            else:
                hboxLayout = QtGui.QHBoxLayout()
                hboxLayout.addWidget(QtGui.QLabel('От:', self))

                if col[2] == 'REAL':
                    fromWidget = QtGui.QDoubleSpinBox()
                    fromWidget.setMaximum(999999999)
                    fromWidget.setSuffix(' руб.')
                    toWidget = QtGui.QDoubleSpinBox()
                    toWidget.setMaximum(999999999)
                    toWidget.setSuffix(' руб.')
                elif col[2] == 'INTEGER':
                    fromWidget = QtGui.QSpinBox()
                    fromWidget.setMaximum(999999999)
                    toWidget = QtGui.QSpinBox()
                    toWidget.setMaximum(999999999)
                elif col[2] == 'DATE':
                    fromWidget = QtGui.QDateEdit(datetime.date.today())
                    toWidget = QtGui.QDateEdit(datetime.date.today())
                else:
                    fromWidget = QtGui.QDateEdit(datetime.datetime.today())
                    toWidget = QtGui.QDateEdit(datetime.datetime.today())

                hboxLayout.addWidget(fromWidget)
                hboxLayout.addWidget(QtGui.QLabel('До:', self))
                hboxLayout.addWidget(toWidget)

                gridLayout.addLayout(hboxLayout, glRow, 3)

        gridLayout.addWidget(buttonBox, glRow + 1, 1, 1, 3, QtCore.Qt.AlignHCenter)

        # Добавление лейаута в диалог и отображение его.
        dialog.setLayout(gridLayout)
        dialog.exec_()

        # Результат диалога.
        if dialog.result() == QtGui.QDialog.Accepted:
            for glRow in range(gridLayout.rowCount() - 1):
                # Определение типа виджета и получение данных.
                checkBox = gridLayout.itemAtPosition(glRow, 1).widget()
                if checkBox.isChecked() == True:
                    label = gridLayout.itemAtPosition(glRow, 2).widget()
                    qobject = gridLayout.itemAtPosition(glRow, 3).widget() or gridLayout.itemAtPosition(glRow, 3).layout()

                    if qobject.inherits('QHBoxLayout'):
                        fromWidget = qobject.itemAt(1).widget()
                        toWidget = qobject.itemAt(3).widget()

                        if fromWidget.inherits('QDoubleSpinBox') and toWidget.inherits('QDoubleSpinBox'):
                            data = (fromWidget.value(), toWidget.value())
                        elif fromWidget.inherits('QSpinBox') and toWidget.inherits('QSpinBox'):
                            data = (fromWidget.value(), toWidget.value())
                        elif fromWidget.inherits('QDateEdit') and toWidget.inherits('QDateEdit'):
                            data = (fromWidget.date().toPython(), toWidget.date().toPython())
                        elif fromWidget.inherits('QDateTimeEdit') and toWidget.inherits('QDateTimeEdit'):
                            data = (fromWidget.dateTime().toPython(), toWidget.dateTime().toPython())
                    elif qobject.inherits('QLineEdit'):
                        data = qobject.text()
                    elif qobject.inherits('QCheckBox'):
                        data = qobject.isChecked()

                    # Получение имени поля таблицы и добавление данных.
                    name = label.text()
                    if data is not None:
                        filters[name] = data

            return filters

        else:
            return None

    def _displayEditNoteDialog(self, clientId: int):
        """
        Отображение диалога оперативной заметки для выбранного клиента с возможностью редактирования.
        """
        clientsTable = self.db.getTable('Клиенты')
        notesTable = self.db.getTable('Заметки')

        currentNote = ''

        noteId = clientsTable.select({'Id': clientId}, ['Заметка'])[0][0]
        if noteId is None:
            noteId = notesTable.addRow({'Оперативная заметка': ''})
            clientsTable.changeRow(clientId, {'Заметка': noteId})
        else:
            currentNote = notesTable.select({'Id': noteId}, ['Оперативная заметка'])[0][0]

        dialog = QtGui.QDialog(self)
        dialog.setWindowTitle('Оперативная заметка')
        dialog.setWindowFlags(QtGui.QWidget.windowFlags(dialog) ^ QtCore.Qt.WindowContextHelpButtonHint)

        buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(dialog.accept)
        buttonBox.rejected.connect(dialog.reject)

        noteWidget = QtGui.QTextEdit()
        noteWidget.setText(currentNote)

        gridLayout = QtGui.QGridLayout()
        gridLayout.addWidget(noteWidget, 0, 1)
        gridLayout.addWidget(buttonBox, 1, 1, QtCore.Qt.AlignHCenter)

        dialog.setLayout(gridLayout)
        dialog.exec_()

        if dialog.result() == QtGui.QDialog.Accepted:
            notesTable.changeRow(noteId, {'Оперативная заметка': noteWidget.toPlainText()})

    def _displayRecordsDialog(self, title: str, columns: list, records: list):
        """
        Отображение диалога, содержащего указанные записи.
        """
        dialog = QtGui.QDialog(self)
        dialog.setWindowTitle(title)
        dialog.setWindowFlags(QtGui.QWidget.windowFlags(dialog) ^ QtCore.Qt.WindowContextHelpButtonHint)
        dialog.setMinimumWidth(len(columns) * len(max(columns)) * (12 * len(min(columns)) / len(max(columns))))

        tableWidget = QtGui.QTableWidget()
        tableWidget.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch)
        tableWidget.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
        tableWidget.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
        tableWidget.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        tableWidget.setColumnCount(len(columns))
        tableWidget.setHorizontalHeaderLabels(columns)
        tableWidget.itemDoubleClicked.connect(functools.partial(self._doubleClicked, tableWidget))

        for record in records:
            tableWidget.setRowCount(tableWidget.rowCount() + 1)
            col = 0
            for item in record:
                tableWidget.setItem(tableWidget.rowCount() - 1, col, QtGui.QTableWidgetItem(item.__str__()))
                col += 1

        buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok)
        buttonBox.accepted.connect(dialog.accept)

        gridLayout = QtGui.QGridLayout()
        gridLayout.addWidget(tableWidget, 0, 1)
        gridLayout.addWidget(buttonBox, 1, 1, 1, 1, QtCore.Qt.AlignHCenter)

        dialog.setLayout(gridLayout)
        dialog.exec_()

    def _displayEditColorDialog(self, clientId: int):
        """
        Отображение диалога изменения цвета записей Клиента.
        """
        clientsTable = self.db.getTable('Клиенты')
        colorsTable = self.db.getTable('Цветовая_дифференциация')

        color = self.db.selectByQuery(
                fromTables="""`Цветовая_дифференциация`
                    JOIN `Клиенты` ON `Цветовая_дифференциация`.`Id` = `Клиенты`.`Цвет`
                """,
                select="""`Цветовая_дифференциация`.`Цвет`""",
                where="""`Клиенты`.`Id` = {}
                """.format(clientId)
        )[0][0]

        qcolor = QtGui.QColorDialog.getColor(QtGui.QColor(color), self, 'Выберите цвет для выделения')
        if not qcolor.isValid():
            return

        for col in range(self.ui.tableClients.columnCount()):
            self.ui.tableClients.item(self.ui.tableClients.currentRow(), col).setBackground(qcolor)

        color = colorsTable.select({'Цвет': qcolor.name()}, ['Id'])
        if len(color) == 0:
            colorId = colorsTable.addRow({'Цвет': qcolor.name()})
        else:
            colorId = color[0][0]

        clientsTable.changeRow(clientId, {'Цвет': colorId})

    def _makeOrder(self, clientId: int):
        """
        Создание нового заказа.
        """
        dialog = ControlNewOrder(clientId, self)
        dialog.setModal(True)
        dialog.show()

    def _payOrder(self, orderId: int):
        """
        Оперативное изменеие статуса оплачено.
        """
        msgBox = QtGui.QMessageBox()
        msgBox.setWindowTitle('Опалата заказа')
        msgBox.setText('Подтверждение оплаты заказа.')
        msgBox.setInformativeText('Вы действительно хотите сделать данный заказ оплаченным?')
        msgBox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
        msgBox.setDefaultButton(QtGui.QMessageBox.Ok)
        msgBox.exec_()

        if msgBox.result() == QtGui.QMessageBox.Ok:
            self.db.getTable('Заказы').changeRow(orderId, {'Оплачено': 1})
            self.ui.tableOrders.setItem(self.ui.tableOrders.currentRow(), 7, QtGui.QTableWidgetItem('Да'))

    def _changePriority(self, clientId: int):
        """
        Оперативное изменение приоритета клиента.
        """
        # Получение выбранной строки.
        selectedRow = self.ui.tableClients.currentRow()

        dialog = QtGui.QDialog(self)
        dialog.setWindowTitle('Изменение приоритета клиента')
        dialog.setWindowFlags(QtGui.QWidget.windowFlags(dialog) ^ QtCore.Qt.WindowContextHelpButtonHint)
        dialog.setMinimumWidth(250)

        buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(dialog.accept)
        buttonBox.rejected.connect(dialog.reject)

        spinBox = QtGui.QSpinBox()
        spinBox.setMaximum(999999999)
        spinBox.setValue(int(self.ui.tableClients.item(selectedRow, 4).text()))

        gridLayout = QtGui.QGridLayout()
        gridLayout.addWidget(QtGui.QLabel('Приоритет: ', self), 0, 1)
        gridLayout.addWidget(spinBox, 0, 2)
        gridLayout.addWidget(buttonBox, 1, 1, 1, 2, QtCore.Qt.AlignHCenter)

        dialog.setLayout(gridLayout)
        dialog.exec_()

        if dialog.result() == QtGui.QDialog.Accepted:
            table = self.db.getTable('Клиенты')
            table.changeRow(clientId, {'Приоритет': spinBox.value()})

            # Столбцы таблицы.
            columns = table.fetchColumnsWithoutForeignKeys()
            # Получение всех записей в таблице отсортированных по приоритету клиентов.
            allRecords = table.select(selectTo=[col[1] for col in columns],orderBy=['Приоритет'], desc=True)
            row = selectedRow
            for row, record in enumerate(allRecords):
                if record[0] == clientId:
                    break

            if row != selectedRow:
                # Удаление текущей строки.
                self.ui.tableClients.removeRow(selectedRow)
                self.ui.tableClients.insertRow(row)

                col = 0
                for item in record:
                    self.ui.tableClients.setItem(row, col,
                        # Вслучаи если это булево поле, то отображать 'Да' или 'Нет'.
                        QtGui.QTableWidgetItem(item.__str__() if columns[col][2] != 'BOOL' else 'Да' if item == 1 else 'Нет')
                    )
                    col += 1
            else:
                self.ui.tableClients.item(row, 4).setText(str(spinBox.value()))

            # Скрытие от пользователя первого столбца таблицы, содержащего первичный ключ.
            self.ui.tableClients.setColumnHidden(0, True)
            # Переход на строку только что созданной записи.
            self.ui.tableClients.selectRow(row)

    def newDataBase(self):
        """
        Создание новой БД.
        """
        dialog = ControlNewDatabase(self)
        dialog.setModal(True)
        dialog.show()

    def loadDatabase(self, filename: str):
        """
        Заргузка БД.
        """
        self.db = PDataBase(filename)
        if len(self.db.tablesNames()) == 0:
            self.db.createTable(
                'Поставщики',
                [
                    (0, 'Id', 'INTEGER'),
                    (1, 'Название', 'VARCHAR'),
                    (2, 'Описание', 'TEXT')
                ],
                [
                    'Id'
                ]
            )

            self.db.createTable(
                'Заметки',
                [
                    (0, 'Id', 'INTEGER'),
                    (1, 'Оперативная заметка', 'TEXT')
                ],
                [
                    'Id'
                ]
            )

            self.db.createTable(
                'Цветовая_дифференциация',
                [
                    (0, 'Id', 'INTEGER'),
                    (1, 'Цвет', 'VARCHAR')
                ],
                [
                    'Id'
                ]
            ).addRow({'Id': 1, 'Цвет': QtGui.QColor(QtCore.Qt.white).name()})

            self.db.createTable(
                'Клиенты',
                [
                    (0, 'Id', 'INTEGER'),
                    (1, 'Название', 'VARCHAR'),
                    (2, 'Контактное лицо', 'VARCHAR'),
                    (3, 'Телефон', 'VARCHAR'),
                    (4, 'Приоритет', 'INTEGER'),
                    (5, 'Местоположение', 'VARCHAR'),
                    (6, 'Адрес', 'VARCHAR'),
                    (7, 'Кол-во сделок', 'INTEGER'),
                    (8, 'Описание', 'TEXT'),
                    (9, 'Заметка', 'INTEGER'),
                    (10, 'Цвет', 'INTEGER')
                ],
                [
                    'Id'
                ],
                [
                    ('Заметка', 'Заметки', 'Id'),
                    ('Цвет', 'Цветовая_дифференциация', 'Id')
                ]
            )

            self.db.createTable(
                'Заказы',
                [
                    (0, 'Id', 'INTEGER'),
                    (1, 'Клиент', 'INTEGER'),
                    (2, 'Наименование', 'VARCHAR'),
                    (3, 'Дата', 'DATE'),
                    (4, 'Время доставки', 'DATE'),
                    (5, 'Дополнительные расходы', 'REAL'),
                    (6, 'Описание', 'TEXT'),
                    (7, 'Оплачено', 'BOOL')
                ],
                [
                    'Id'
                ],
                [
                    ('Клиент', 'Клиенты', 'Id')
                ]
            )

            self.db.createTable(
                'Товары',
                [
                    (0, 'Id', 'INTEGER'),
                    (1, 'Наименование', 'VARCHAR'),
                    (2, 'Артикул', 'VARCHAR'),
                    (3, 'Бренд', 'VARCHAR'),
                    (4, 'Кол-во', 'INTEGER'),
                    (5, 'Стоимость', 'REAL'),
                    (6, 'Категория', 'VARCHAR'),
                    (7, 'Страна', 'VARCHAR'),
                    (8, 'Дата', 'DATE')
                ],
                [
                    'Id'
                ]
            )

            self.db.createTable(
                'Товары_Заказы',
                [
                    (0, 'Товар', 'INTEGER'),
                    (1, 'Заказ', 'INTEGER'),
                    (2, 'Кол-во', 'INTEGER'),
                    (3, 'Поставщик', 'INTEGER')
                ],
                [],
                [
                    ('Товар', 'Товары', 'Id'),
                    ('Заказ', 'Заказы', 'Id'),
                    ('Поставщик', 'Поставщики', 'Id')
                ]
            )
        
        for pair in zip([self.ui.tableOrders, self.ui.tableClients, self.ui.tableGoods, self.ui.tableProviders], ['Заказы', 'Клиенты', 'Товары', 'Поставщики']):
            self._initTable(pair[0], pair[1])

        self.ui.tableOrders.setColumnCount(self.ui.tableOrders.columnCount() + 1 ) # добавляем столбец с итоговой суммой
        self.ui.tableOrders.setHorizontalHeaderItem(self.ui.tableOrders.columnCount() - 1, QtGui.QTableWidgetItem('Сумма'))
        for i in range(0, self.ui.tableOrders.rowCount()):
            stuff = self.db.selectByQuery(
                fromTables="""`Товары_Заказы`, `Товары`""",
                select="""SUM(`Товары_Заказы`.`Кол-во` * `Товары`.`Стоимость`)""",
                where="""`Товары`.`Id` = `Товары_Заказы`.`Товар` AND `Товары_Заказы`.`Заказ` = {}""".format(self.ui.tableOrders.item(i, 0).text())
            )[0][0]
            self.ui.tableOrders.setItem(
                i,
                self.ui.tableOrders.columnCount() - 1,
                QtGui.QTableWidgetItem(str(stuff))
            )

        self.ui.menuRecord.setEnabled(True)
        self.ui.tabWidget.setEnabled(True)  
                   
    def exit(self):
        """
        Выход из программы.
        """
        self.close()
        
    def closeDatabase(self):
        """
        Закрытие данной БД.
        """
        if self.db != None:
            self.db = None
            self.ui.menuRecord.setEnabled(False)
            self.ui.tabWidget.setEnabled(False) 
        
    def openDatabase(self):
        """
        Открытие БД.
        """
        path = QtGui.QFileDialog.getOpenFileName(self, 'Открытие базы данных', '')[0]
        if path != '':
            if self.db != None:
                self.closeDatabase()
            if os.path.exists(path):
                try:
                    self.loadDatabase(path)
                except Exception:
                    QtGui.QMessageBox.warning(self, 'Внимание', 'Произошла ошибка при открытии базы данных. Возможно файл повреждён или не является файлом базы данных.')
            else:
                QtGui.QMessageBox.warning(self, 'Внимание', 'Указанного файла не существует!')

    def newRecord(self):
        """
        Создание новой записи таблицы.
        """
        # Полученеи индекса текущего вкладки.
        index = self.ui.tabWidget.currentIndex()
        if index == -1:
            return
        # Получение таблицы из БД, по имени текущей вкладки.
        table = self.db.getTable(self.ui.tabWidget.tabText(index))
        # Получение столбцов таблицы без учета вторичных ключей.
        columns = table.fetchColumnsWithoutForeignKeys()

        # Отображение пользовательского диалога для заполнения полей новой записи.
        newRecord = self._displayEditRecordDialog('Добавление новой записи в таблицу "{}"'.format(table.name), table)
        if len(newRecord) == 0:
            return

        if table.name == 'Клиенты':
            newRecord['Цвет'] = 1

        # Получение Id добавленной записи.
        id = table.addRow(newRecord)

        # Получение таблицы-виджета и отображение только-что созданной записи.
        tableWidget = self.ui.tabWidget.currentWidget().layout().itemAtPosition(0, 0).widget()
        # Позиция вставки строки в таблицу.
        row = tableWidget.rowCount()

        if table.name == 'Заказы':
            columns = table.columns
            columns[1] = (1, 'Клиент', 'VARCHAR')
            record = self.db.selectByQuery(
                fromTables="""`Заказы`, `Клиенты`""",
                select="""`Заказы`.`Id`, `Заказы`.`Наименование`, `Клиенты`.`Название`, `Заказы`.`Дата`, `Заказы`.`Время доставки`, `Заказы`.`Дополнительные расходы`, `Заказы`.`Описание`, `Заказы`.`Оплачено`""",
                where="""{} = `Клиенты`.`Id`""".format(id)
            )[0]
        elif table.name == 'Клиенты':
            # Получение столбцов таблицы без учета вторичных ключей.
            columns = table.fetchColumnsWithoutForeignKeys()
            # Для таблицы "Клиенты" идет сортировка по убыванию по столбцу "Приоритет".
            # Получение всех записей в таблице отсортированных по приоритету клиентов
            allRecords = table.select(selectTo=[col[1] for col in columns],orderBy=['Приоритет'], desc=True)
            for row, record in enumerate(allRecords):
                if record[0] == id:
                    break
        else:
            # Получение столбцов таблицы без учета вторичных ключей.
            columns = table.fetchColumnsWithoutForeignKeys()
            # Получение всех записей в таблице отсортированных по приоритету клиентов
            record = table.select({'Id': id}, [col[1] for col in columns])[0]

        tableWidget.insertRow(row)
        col = 0
        for item in record:
            tableWidget.setItem(row, col,
                # Вслучаи если это булево поле, то отображать 'Да' или 'Нет'.
                QtGui.QTableWidgetItem(item.__str__() if columns[col][2] != 'BOOL' else 'Да' if item == 1 else 'Нет')
            )
            col += 1

        # Скрытие от пользователя первого столбца таблицы, содержащего первичный ключ.
        tableWidget.setColumnHidden(0, True)
        # Переход на строку только что созданной записи.
        tableWidget.selectRow(row)

    def deleteRecord(self):
        """
        Удаление записи таблицы.
        """
        # Полученеи индекса текущего вкладки.
        index = self.ui.tabWidget.currentIndex()
        if index == -1:
            return

        # Получение таблицы-виджета.
        tableWidget = self.ui.tabWidget.currentWidget().layout().itemAtPosition(0, 0).widget()
        # Полученеи текущей выбранной строки в таблицы-виджета.
        selectedRow = tableWidget.currentRow()
        if selectedRow == -1:
            return

        # Получение таблицы из БД, по имени текущей вкладки.
        table = self.db.getTable(self.ui.tabWidget.tabText(index))

        # Отображение диалога-подтверждения удаления записи.
        msgBox = QtGui.QMessageBox()
        msgBox.setWindowTitle('Удаление записи')
        msgBox.setText('Подтверждение удаление записи из таблицы "{}".'.format(table.name))
        msgBox.setInformativeText('Вы действительно хотите удалть эту запись?')
        msgBox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
        msgBox.setDefaultButton(QtGui.QMessageBox.Ok)
        msgBox.exec_()

        if msgBox.result() == QtGui.QMessageBox.Ok:
            # Удаление записи таблицы БД и из таблицы-виджета.
            table.deleteRow(int(tableWidget.item(selectedRow, 0).text()))
            tableWidget.removeRow(selectedRow)

    def editRecord(self):
        """
        Редактированеи записи таблицы.
        """
        if self.ui.tabWidget.currentIndex() == -1:
            return

        # Получение таблицы-виджета.
        tableWidget = self.ui.tabWidget.currentWidget().layout().itemAtPosition(0, 0).widget()
        # Полученеи текущей выбранной строки в таблицы-виджета.
        selectedRow = tableWidget.currentRow()
        if selectedRow == -1:
            return

        # Получение таблицы из БД, по имени текущей вкладки.
        table = self.db.getTable(self.ui.tabWidget.tabText(self.ui.tabWidget.currentIndex()))
        # Получение Id изменяемой записи.
        id = int(tableWidget.item(selectedRow, 0).text())
        # Полученеи выбранной записи.
        record = table.select({'Id': id})[0]
        # Получение столбцов таблицы без учета вторичных ключей.
        columns = table.fetchColumnsWithoutForeignKeys()
        # Отображение пользовательского диалога для заполнения полей редактируемой записи.
        record = self._displayEditRecordDialog('Редактирование записи в таблице "{}"'.format(table.name), table, {col[1]: record[col[0]] for col in columns})
        if len(record) == 0:
            return
        table.changeRow(id, record)

        # Позиция вставки строки в таблицу.
        row = selectedRow
        color = tableWidget.item(selectedRow, 0).background()
        # Изменение записи в таблице БД.
        if table.name == 'Заказы':
            columns = table.columns
            columns[1] = (1, 'Клиент', 'VARCHAR')
            record = self.db.selectByQuery(
                fromTables="""`Заказы`, `Клиенты`""",
                select="""`Заказы`.`Id`, `Заказы`.`Наименование`, `Клиенты`.`Название`, `Заказы`.`Дата`, `Заказы`.`Время доставки`, `Заказы`.`Дополнительные расходы`, `Заказы`.`Описание`, `Заказы`.`Оплачено`""",
                where="""{} = `Клиенты`.`Id`""".format(id)
            )[0]
        elif table.name == 'Клиенты':
            # Для таблицы "Клиенты" идет сортировка по убыванию по столбцу "Приоритет".
            # Получение всех записей в таблице отсортированных по приоритету клиентов
            allRecords = table.select(selectTo=[col[1] for col in columns],orderBy=['Приоритет'], desc=True)
            for row, record in enumerate(allRecords):
                if record[0] == id:
                    break

            if row != selectedRow:
                # Удаление текущей строки.
                tableWidget.removeRow(selectedRow)
                tableWidget.insertRow(row)
        else:
            # Получение созданной записи в соответсвии с порядком следования столбцов в таблице и новым id.
            record = table.select({'Id': id}, [col[1] for col in columns])[0]

        col = 0
        for item in record:
            tableWidgetItem = QtGui.QTableWidgetItem(item.__str__() if columns[col][2] != 'BOOL' else 'Да' if item == 1 else 'Нет')
            tableWidgetItem.setBackground(color)
            tableWidget.setItem(row, col, tableWidgetItem)
            col += 1

        # Скрытие от пользователя первого столбца таблицы, содержащего первичный ключ.
        tableWidget.setColumnHidden(0, True)
        # Переход на строку только что созданной записи.
        tableWidget.selectRow(row)

    def searchRecord(self):
        """
        Поиск записи по критериям.
        """
        # Полученеи индекса текущего вкладки.
        index = self.ui.tabWidget.currentIndex()
        if index == -1:
            return

        # Получение таблицы из БД, по имени текущей вкладки.
        table = self.db.getTable(self.ui.tabWidget.tabText(index))
        columns = [col[1] for col in table.fetchColumnsWithoutKeys()]

        filters = self._displaySearchRecordDialog('Поиск записи по критериям в таблице "{}"'.format(table.name), table)
        if filters is None:
            return

        records = table.select(filters, columns) if len(filters) != 0 else []

        # Отображение диалога поиска записей по критериям.
        self._displayRecordsDialog('Найденные записи в таблице "{}"'.format(table.name), columns, records)

    def showAboutProgramm(self):
        """
        Показ справки.
        """
        dialog = QtGui.QDialog(self)
        dialog.setWindowTitle('О программе')
        dialog.setWindowFlags(QtGui.QWidget.windowFlags(dialog) ^ QtCore.Qt.WindowContextHelpButtonHint)
        dialog.setMinimumSize(550, 100)

        textBrowser = QtGui.QTextBrowser()
        textBrowser.setHtml(
            """
            <!DOCTYPE html>
                <html>
                    <head>
                        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
                        <title>О программе</title>
                    </head>
                    <body>
                        <header>
                            <h1 align="center">Программа "База данных ГП &#171;Формула&#187;"</h1>
                        </header>

                        <div id="content">
                            <h2 align="center">Версия 1.0.1</h2>
                            <h3 align="center">Copyright (c) 2013 Иванов В. и Руднев Р.</h1>
                        </div>
                        <hr/>
                        <div id="footer" align="center">
                            <a href="http://ru.wikipedia.org/wiki/GNU_General_Public_License">GNU General Public License</a>
                        </div>
                    </body>
                </html>
            """
        )

        buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok)
        buttonBox.accepted.connect(dialog.accept)

        gridLayout = QtGui.QGridLayout()
        gridLayout.addWidget(textBrowser, 0, 1)
        gridLayout.addWidget(buttonBox, 1, 1, 1, 1, QtCore.Qt.AlignHCenter)

        dialog.setLayout(gridLayout)
        dialog.exec_()

    def showReference(self):
        """
        Показ окна о программе.
        """
        dialog = QtGui.QDialog(self)
        dialog.setWindowTitle('Справка')
        dialog.setWindowFlags(QtGui.QWidget.windowFlags(dialog) ^ QtCore.Qt.WindowContextHelpButtonHint)
        dialog.setMinimumSize(800, 820)

        textBrowser = QtGui.QTextBrowser()
        textBrowser.setHtml(
            """
            <!DOCTYPE html>
                <html>
                    <head>
                        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
                        <title>Справка</title>
                    </head>
                    <body>
                        <header>
                            <h1 align="center">Справка по "База данных ГП &#171;Формула&#187;"</h1>
                        </header>

                        <div id="content">
                                <p id="intro">Программа "База данных ГП &#171;Формула&#187;" предназанчена для учёта клиентов, поставщиков,
                                    товаров и заказов, которые всех и их связывают.</p>
                                <div id="menu">
                                    <h3>Содержание</h3>
                                <ul>
                                   <li><a href="#common">Общие сведения</a></li>
                                   <li><a href="#bdwork">Работа с базами даных</a></li>
                                   <li><a href="#recordwork">Работа с записями</a></li>
                                   <li><a href="#orderwork">Оформление заказа</a></li>
                                </ul>
                            </div>
                            <hr/>
                            <div id="helpcontent">
                                <div class="helpitem">
                                    <h3><a name="common">Общие сведения</a></h3>
                                        <p>
                                            Главное окно программы предоставляет доступ к непосредственной работе с клиентами, поставщиками, товарами и заказами.
                                            Данные об указанных сущностях представлены в табличной форме, где столбцы проименованы в соответствии с их атрибутами.
                                            Все таблицы имеют контекстные меню, которые показываются при щелчке правой кнопке мыши по какой-либо строке этих таблиц.
					                        В них представлены дополнительные функции, которые недоступны через главное меню. В таблице "Заказы" таким образом можно
					                        отметить выбранный заказ, как оплаченный; просмотреть заказанные товары; просмотреть поставщиков. В таблице "Клиенты" из
					                        контекстного меню можно: создать новый заказ вязанный с выбранным клиентом, просмотреть оплаченные и неоплаченные им заказы,
					                        изменить его приоритет, сделать оперативную заметку и выделить цветом. В таблице "Товары" из контекстного меню можно узнать
					                        все заказы с выбранным товаром. В таблице "Поставщики" можно просмотреть все заказы с выбранным поставщиком. В таблице "Заказы"
					                        поле сумма расчитывается, как сумма стоимостей всех заказанных товаров помноженных на их количество.
                                        </p>
                                </div>
                                <div class="helpitem">
                                    <h3><a name="bdwork">Работа с базами даных</a></h3>
                                        <p>
                                            Раздел меню "База данных" предоставляет доступ к функциям работы с базами данных. Здесь вы можете создать новую,
                                            открыть существующую и закрыть открытую базу данных. При создании новой базы данных вы увидете диалогове окно,
                                            в котором вам необходимо задать имя новой БД и выбрать место в файловой системе, где она будет храниться. Пустое
                                            имя не допускается. При открытии БД вам необходимо лишь выбрать её файл, вся остальная подгрузка осуществится автоматически.
                                        </p>
                                </div>
                                <div class="helpitem">
                                    <h3><a name="recordwork">Работа с записями</a></h3>
                                        <p>
                                            Раздел меню "Запись" предоставляет доступ к таким функциям как: создание новой записи, редактирование и удаление существующей.
                                            Также здесь находится переход к поиску по критериям. Данный раздел меню зависит от выбранной в данной момент таблицы. Например,
                                            если выбранна таблица "Клиенты", то создание, редактирование, удаление и поиск будут осуществляться в этой таблице.
                                        </p>
                                        <p>
                                            При создании новой записи появляется диалогове окно, в котором необходимо заполнить поля с данным будущей записи. При этом там
                                            будут находится поля нужные для выбранной в данной момент таблицы. Тоже самое справедливо и для редактирования существующей записи.
                                            <br /><i>Примечание: при выборе таблицы "Заказы" пункт "Создать новую" в меню "Запись" будет заблокирован.</i>
                                        </p>
                                        <p>
                                            При выборе пукта "Поиск по критериям" появляется диалоговое окно, где расположены поля для заполнения, которые и есть критерии поиска.
                                            При этом наличие критериев зависит от выбранной таблицы. После заполнения полей-критериев запуск поиска производится кнопкой "Ok".
                                            После этого появится диалогове окно с результатами поиска, где в табличном виде отобразятся записи, попавшие под заданние условия.
                                        </p>
                                </div>
                                <div class="helpitem">
                                    <h3><a name="orderwork">Оформление заказа</a></h3>
                                        <p>
                                            Для создания нового заказа откройте таблицу "Клиенты" и выберите клиента, с которым будет связан будущий заказ. Затем щёлкните по этой
                                            строке таблицы правой кнопкой мыши и в появившемся контекстном меню выберите "Сделать заказ". Появится диалогове окно с параметрами заказа,
                                            которые нужно заполнить. Для добавления товаров в данный заказ нажмите нажмите на кнопку "Выбрать". При этом появится новое диалогове окно, где
                                            будет две секции. Правая с заголовком "Доступные" содержит доступные для добавления товары. Левая с заголовком "Текущие" содержит, добавленные
                                            в текущий заказ товары. Чтобы перемещать товары слева направо и наоборот, необходимо использовать кнопки ">>" и "<<" соответственно, которые
                                            расположены между секциями. При перемещинии из "Доступных" в "Текущие" появится окно, в котором необходимо указать количество заказываемого
                                            товара и поставщика связанного с ним. После заполненния всех полей в окне нового заказа нажмите кнопку "Ok", и заказ добавится в таблицу "Заказы".
                                            При этом только что созданный заказ имеет получает статус "Неоплаченный".
                                        </p>
                                </div>
                            </div>
                        </div>

                        <div id="footer" align="center">
                            &#169; 2013 <a href="mailto:zlumyo@gmail.com">Владимир Иванов</a>, <a href="mailto:rudrom15@gmail.com">Руднев Роман</a>
                        </div>
                    </body>
                </html>
            """
        )

        buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok)
        buttonBox.accepted.connect(dialog.accept)

        gridLayout = QtGui.QGridLayout()
        gridLayout.addWidget(textBrowser, 0, 1)
        gridLayout.addWidget(buttonBox, 1, 1, 1, 1, QtCore.Qt.AlignHCenter)

        dialog.setLayout(gridLayout)
        dialog.exec_()

    def ordersContextMenu(self, pos):
        """
        Отображение меню для таблицы 'Заказы'.
        """
        selectedRow = self.ui.tableOrders.currentRow()
        if selectedRow == -1:
            return

        id = int(self.ui.tableOrders.item(selectedRow, 0).text())

        menu = QtGui.QMenu(self)
        pay = menu.addAction('Пометить как оплаченный ...')
        menu.addSeparator()
        goodsWithProviders = menu.addAction('Просмотреть заказанные товары')
        providers = menu.addAction('Просмотреть поставщиков')

        target = menu.exec_(self.ui.tableOrders.viewport().mapToGlobal(pos))

        if target == pay:
            if self.ui.tableOrders.item(selectedRow, 7).text() == 'Нет':
                self._payOrder(id)
            else:
                QtGui.QMessageBox.information(self, 'Оплата заказа', 'Заказ уже оплачен!')
        elif target == goodsWithProviders:
            records = self.db.selectByQuery(
                fromTables="""`Заказы`
                    JOIN `Товары_Заказы` ON `Товары_Заказы`.`Заказ` = `Заказы`.`Id`
                    JOIN `Товары` ON `Товары_Заказы`.`Товар` = `Товары`.`Id`
                    JOIN `Поставщики` ON `Товары_Заказы`.`Поставщик` = `Поставщики`.`Id`
                """,
                select="""`Товары`.`Артикул`, `Товары`.`Наименование`, `Поставщики`.`Название`, `Товары`.`Стоимость`, `Товары_Заказы`.`Кол-во`""",
                where="""
                    `Заказы`.`Id` = {}
                """.format(id)
            )
            self._displayRecordsDialog('Товары, входящие в заказ', ['Артикул товара', 'Товар', 'Поставщик', 'Цена', 'Количество'], records)
        elif target == providers:
            records = self.db.selectByQuery(
                fromTables="""`Заказы`
                    JOIN `Товары_Заказы` ON `Товары_Заказы`.`Заказ` = `Заказы`.`Id`
                    JOIN `Поставщики` ON `Товары_Заказы`.`Поставщик` = `Поставщики`.`Id`
                """,
                select="""`Поставщики`.`Название`""",
                where="""
                    `Заказы`.`Id` = {}
                """.format(id)
            )
            self._displayRecordsDialog('Поставщики, участвующие в заказе', ['Поставщик'], records)

    def clientsContextMenu(self, pos):
        """
        Отображение меню для таблицы 'Клиенты'.
        """
        selectedRow = self.ui.tableClients.currentRow()
        if selectedRow == -1:
            return

        id = int(self.ui.tableClients.item(selectedRow, 0).text())

        menu = QtGui.QMenu(self)
        order = menu.addAction('Сделать заказ ...')
        priority = menu.addAction('Изменить приоритет ...')
        notice = menu.addAction('Оперативная заметка ...')
        color = menu.addAction('Выделить цветом ...')
        menu.addSeparator()
        payed = menu.addAction('Оплаченные заказы')
        wished = menu.addAction('Желаемые заказы')

        target = menu.exec_(self.ui.tableClients.viewport().mapToGlobal(pos))

        if target == notice:
            self._displayEditNoteDialog(id)
        elif target == payed:
            names = self.db.getTable('Клиенты').select({'Id': id}, ['Название', 'Контактное лицо'])[0]
            columns = ['Наименование', 'Дата', 'Время доставки', 'Дополнительные расходы', 'Описание']
            records = self.db.getTable('Заказы').select({'Клиент': id, 'Оплачено': 1}, columns)
            self._displayRecordsDialog('Оплаченные заказы {0}{1}'
                                       .format(names[0] if len(names[0]) != 0 else '', ' {}'.format(names[1]) if len(names[1]) != 0 else ''), columns, records)
        elif target == wished:
            names = self.db.getTable('Клиенты').select({'Id': id}, ['Название', 'Контактное лицо'])[0]
            columns = ['Наименование', 'Дата', 'Время доставки', 'Дополнительные расходы', 'Описание']
            records = self.db.getTable('Заказы').select({'Клиент': id, 'Оплачено': 0}, columns)
            self._displayRecordsDialog('Желаемые заказы {0}{1}'
                                       .format(names[0] if len(names[0]) != 0 else '', ' {}'.format(names[1]) if len(names[1]) != 0 else ''), columns, records)
        elif target == order:
            self._makeOrder(id)
        elif target == priority:
            self._changePriority(id)
        elif target == color:
            self._displayEditColorDialog(id)

    def goodsContextMenu(self, pos):
        """
        Отображение меню для таблицы 'Товары'.
        """
        selectedRow = self.ui.tableGoods.currentRow()
        if selectedRow == -1:
            return

        id = int(self.ui.tableGoods.item(selectedRow, 0).text())

        menu = QtGui.QMenu(self)
        ordersWithGoods = menu.addAction('Просмотреть все заказы с данным товаром')

        target = menu.exec_(self.ui.tableGoods.viewport().mapToGlobal(pos))

        if target == ordersWithGoods:
            records = self.db.selectByQuery(
                fromTables="""`Заказы`
                    JOIN `Клиенты` ON `Заказы`.`Клиент` = `Клиенты`.`Id`
                    JOIN `Товары_Заказы` ON `Товары_Заказы`.`Заказ` = `Заказы`.`Id`
                    JOIN `Товары` ON `Товары_Заказы`.`Товар` = `Товары`.`Id`
                """,
                select="""DISTINCT `Заказы`.`Наименование`, `Клиенты`.`Название`, `Заказы`.`Дата`""",
                where="""
                    `Заказы`.`Id` = {}
                """.format(id)
            )
            self._displayRecordsDialog('Заказы, где есть данный товар', ['Заказ', 'Клиент', 'Дата'], records)

    def providersContextMenu(self, pos):
        """
        Отображение меню для таблицы 'Поставщики'.
        """
        selectedRow = self.ui.tableProviders.currentRow()
        if selectedRow == -1:
            return

        id = int(self.ui.tableProviders.item(selectedRow, 0).text())

        menu = QtGui.QMenu(self)
        ordersWithProviders = menu.addAction('Просмотреть все заказы с данным поставщиком')

        target = menu.exec_(self.ui.tableProviders.viewport().mapToGlobal(pos))

        if target == ordersWithProviders:
            records = self.db.selectByQuery(
                fromTables="""`Заказы`
                    JOIN `Клиенты` ON `Заказы`.`Клиент` = `Клиенты`.`Id`
                    JOIN `Товары_Заказы` ON `Товары_Заказы`.`Заказ` = `Заказы`.`Id`
                    JOIN `Поставщики` ON `Товары_Заказы`.`Поставщик` = `Поставщики`.`Id`
                """,
                select="""DISTINCT `Заказы`.`Наименование`, `Клиенты`.`Название`, `Заказы`.`Дата`""",
                where="""
                    `Заказы`.`Id` = {}
                """.format(id)
            )
            self._displayRecordsDialog('Заказы, где участвует данный поставщик', ['Заказ', 'Клиент', 'Дата'], records)